package com.yhb.controller;

import com.yhb.controller.form.LoginForm;
import com.yhb.controller.form.ResetPasswordVerifyForm;
import com.yhb.controller.form.SimpleVerifyCodeForm;
import com.yhb.controller.out.form.CommonRequestForm;
import com.yhb.controller.vo.*;
import com.yhb.model.Certificate;
import com.yhb.model.CpsLevel;
import com.yhb.model.User;
import com.yhb.service.CpsService;
import com.yhb.service.SplittingService;
import com.yhb.service.UserService;
import com.yhb.service.VerifyCodeService;
import com.yhb.utils.DateUtils;
import lombok.extern.log4j.Log4j;
import lombok.var;
import me.edzh.spring.bootstrap.annotations.CurrentUser;
import me.edzh.spring.bootstrap.annotations.EncryptedRequestBody;
import me.edzh.spring.bootstrap.annotations.NeedAuth;
import me.edzh.spring.bootstrap.annotations.SignedRequestBody;
import me.edzh.spring.bootstrap.model.HashMapWrapper;
import me.edzh.spring.bootstrap.model.Response;
import me.edzh.spring.bootstrap.service.ObjectiveStorageService;
import me.edzh.spring.bootstrap.service.SMSService;
import me.edzh.spring.bootstrap.utils.ListUtils;
import me.edzh.spring.bootstrap.utils.MathUtils;
import me.edzh.spring.bootstrap.utils.ResultCode;
import me.edzh.spring.bootstrap.utils.StringUtils;
import me.edzh.spring.bootstrap.utils.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@RestController
@RequestMapping("/user")
@Log4j
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private SMSService aliyunSMS;

    @Autowired
    private VerifyCodeService verifyCodeService;

    @Lazy
    @Autowired
    private SplittingService splittingService;

    @Autowired
    private CpsService cpsService;

    @Qualifier("ossServiceImpl")
    @Autowired
    private ObjectiveStorageService objectiveStorageService;

    @PostMapping("/login")
    public Response<AuthVo> login(@EncryptedRequestBody LoginForm form) {
        AuthVo vo = userService.login(form.getMobile(), form.getPwd());
        fillUserInfo(vo.getUser(), vo.getUser().getUser().getId());
        return new Response<>(vo);
    }

    @PostMapping("/verifyCode")
    public Response getVerifyCode(@SignedRequestBody LoginForm form) {
        return getVerifyCodeInternal(form);
    }

    @CrossOrigin({"https://public.static.ylmvip.cn", "http://localhost:8848"})
    @PostMapping("/verifyCodeH5")
    public Response getVerifyCodeH5(LoginForm form) {
        return getVerifyCodeInternal(form);
    }

    private Response getVerifyCodeInternal(LoginForm form) {
        String verifyCode = verifyCodeService.generateVerifyCode(form.getMobile(), VerifyCodeService.CodeType.REGISTER);
        Map<String, String> p = new HashMap<>();
        p.put("code", verifyCode);
        aliyunSMS.sendSms(form.getMobile(), "SMS_174025663", p);
        return new Response();
    }

    @PostMapping("/register")
    public Response<AuthVo> register(@EncryptedRequestBody LoginForm form) {
        return registerInternal(form);
    }

    @CrossOrigin({"https://public.static.ylmvip.cn", "http://localhost:8848", "https://051qmw.coding-pages.com"})
    @PostMapping("/registerH5")
    public Response registerH5(LoginForm form) {
        registerInternal(form);
        return Response.ok();
    }

    public Response<AuthVo> registerInternal(LoginForm form) {
        if (!verifyCodeService.verifyCode(form.getMobile(), form.getVerifyCode(), VerifyCodeService.CodeType.REGISTER)) {
            throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "验证码错误");
        }


        AuthVo vo = userService.register(User.builder().
                mobile(form.getMobile())
                .password(form.getPwd())
                .build(), form.getInviteCode());
        fillUserInfo(vo.getUser(), vo.getUser().getUser().getId());
        return new Response<>(vo);
    }



    @CrossOrigin({"https://public.static.ylmvip.cn", "http://localhost:8848", "https://051qmw.coding-pages.com"})
    @GetMapping("/invite/{code}/check")
    public Response<Certificate> checkInviteCode(@PathVariable("code")String code) {
        return new Response<>(Certificate.builder().name(userService.getUserNameByInviteCode(code)).build());
    }

    @GetMapping("/{userId}/info")
    @NeedAuth
    public Response<UserInfoVo> getMyInfo(@CurrentUser User user, @PathVariable("userId")String userId) {
        log.info("userId" + userId);
        User result = userService.getUser(userId);
        UserInfoVo vo = new UserInfoVo();
        if (!user.getId().equals(userId)) { // 非本人干掉敏感信息
            user.setMobile(StringUtils.getMaskString(user.getMobile()));
            vo.setCpsRelationId(null);
            // 非本人要干掉敏感信息
        } else {
            vo.setUser(result);
            fillUserInfo(vo, user.getId());
        }

        return Response.ok(vo);
    }

    @PostMapping("/certificate")
    @NeedAuth
    public Response certificate(@CurrentUser User user, @EncryptedRequestBody Certificate certificate) {
        userService.addCertificateInfo(certificate, user);
        return Response.ok();
    }

    @PostMapping("/modify")
    @NeedAuth
    public Response modifyUserInfo(@RequestBody User user, @CurrentUser User currentUser) {
        userService.modifyUser(User.builder()
                .id(currentUser.getId())
                .avatar(user.getAvatar())
                .nickname(currentUser.getNickname())
                .build()
        );

        return Response.ok();
    }

    @PostMapping("/followers/dailyInvitingRank")
    @NeedAuth
    public Response<ArrayWrapperVo<UserInfoVo>> getDailyInviteRank(@SignedRequestBody HashMapWrapper emptyBody, @CurrentUser User user) {
        var users = userService.getFollowerVipActivationRank("DAILY",  user.getId());
        List<UserInfoVo> result = ListUtils.newList(
                users,
                u -> {
                    var vo = fillUserInfo(UserInfoVo.builder()
                            .user(u.getValue1())
                            .build(), user.getId());

                    vo.setConditionedFollowerCount(u.getValue2());

                    return vo;
                }
        );

        return Response.ok(new ArrayWrapperVo<>(result));


    }

    @PostMapping("/followers/monthlyInvitingRank")
    @NeedAuth
    public Response<ArrayWrapperVo<UserInfoVo>> getMonthlyInviteRank(@SignedRequestBody HashMapWrapper emptyBody, @CurrentUser User user) {
        var users = userService.getFollowerVipActivationRank("MONTHLY",  user.getId());
        List<UserInfoVo> result = ListUtils.newList(
                users,
                u -> {
                    var vo = fillUserInfo(UserInfoVo.builder()
                            .user(u.getValue1())
                            .build(), user.getId());

                    vo.setConditionedFollowerCount(u.getValue2());

                    return vo;
                }
        );


        return Response.ok(new ArrayWrapperVo<>(result));

    }

    @PostMapping("/followers/totalInvitingRank")
    @NeedAuth
    public Response<ArrayWrapperVo<UserInfoVo>> getIncomeRank(@SignedRequestBody HashMapWrapper emptyBody, @CurrentUser User user) {
        var users = userService.getFollowerVipActivationRank("TOTAL",  user.getId());
        List<UserInfoVo> result = ListUtils.newList(
                users,
                u -> {
                    var vo = fillUserInfo(UserInfoVo.builder()
                            .user(u.getValue1())
                            .build(), user.getId());

                    vo.setConditionedFollowerCount(u.getValue2());

                    return vo;
                }
        );


        return Response.ok(new ArrayWrapperVo<>(result));

    }

    @PostMapping("/followers/actively")
    @NeedAuth
    public Response<SingleValueWrapVo<String>> getActivelyFollowers(@SignedRequestBody HashMapWrapper emptyBody, @CurrentUser User user) {
        var level = cpsService.getCpsLevel(user.getId());
        return Response.ok(new SingleValueWrapVo<>("" + level.getActiveCount()));
    }

    @PostMapping("/changeNumber")
    @NeedAuth
    public Response<SimpleVerifyCodeTokenVo> changeNumber(@EncryptedRequestBody User user, @CurrentUser User currentUser) {
        return Response.ok(SimpleVerifyCodeTokenVo.builder()
                .token(userService.getChangePhoneNumberSms(currentUser.getId(), user.getMobile()))
                .build());
    }

    @PostMapping("/verifyChangeNumber")
    @NeedAuth
    public Response verifyChangeNumber(@SignedRequestBody SimpleVerifyCodeForm form, @CurrentUser User user) {
        userService.verifyChangePhoneNumber(user.getId(), form.getToken(), form.getVerifyCode());

        return Response.ok();
    }

    @PostMapping("/resetPassword")
    public Response<SimpleVerifyCodeTokenVo> resetPassword(@SignedRequestBody User user) {
        return Response.ok(SimpleVerifyCodeTokenVo.builder()
                .token(userService.getResetPasswordSms(user.getMobile()))
                .build());
    }

    @PostMapping("/verifyResetPassword")
    public Response verifyResetPassword(@EncryptedRequestBody ResetPasswordVerifyForm form) {
        userService.verifyResetPassword(form.getToken(), form.getVerifyCode(), form.getNewPassword());

        return Response.ok();
    }

    @PostMapping("/genThirdAuthCode")
    @NeedAuth
    public Response<AuthVo> genThirdAuthCode(@SignedRequestBody  CommonRequestForm form, @CurrentUser User user) {
        return Response.ok(AuthVo.builder().token(userService.genThirdAuthCode(form.getAppId(), user.getId())).build());
    }


    private UserInfoVo fillUserInfo(UserInfoVo userInfoVo, String currentUserId) {

        var user = userInfoVo.getUser();
        String avatarUrl = user.getAvatar();

        if (avatarUrl != null) {
            user.setAvatar(objectiveStorageService.signUrl(avatarUrl));
        }

        Certificate certificate = userService.getCertificate(userInfoVo.getUser().getId());
        if (certificate != null) {
            userInfoVo.getUser().setCertificate(Certificate.builder().name(certificate.getName()).build());
        }

        var cpsLevel = cpsService.getCpsLevel(user.getId());

        var lastMonthLastMoment = DateUtils.getMonthLastDayLastSecond(DateUtils.getLastMonthFirstDay().getTime());
        var lastMonthCpsLevel = Optional.ofNullable(cpsService.getCpsLevelInDate(user.getId(), DateUtils.getDateString(lastMonthLastMoment))).map(CpsLevel::getLevel).orElse(1L).intValue();

        userInfoVo.setFollowerCount(cpsLevel.getFollowersCount());
        userInfoVo.setVipCps((long)lastMonthCpsLevel);
        userInfoVo.setActiveCountCps(cpsLevel.getActiveCount());
        userInfoVo.setVip5CountCps(cpsLevel.getVip5Count());

        User invitor = userService.getInvitor(userInfoVo.getUser().getId());
        if (invitor != null) {
            userInfoVo.setInvitorName(userService.getUserNameByUserIdUnmasked(invitor.getId()));
            userInfoVo.setInvitorMobile(invitor.getMobile());
        }

        var monthString = DateUtils.getLastMonthString();
        var currentMonthString = DateUtils.getCurrentMonthString();
        try {
            var sumUp = splittingService.getMonthlySumUp(SplittingService.TYPE_ONLINE, monthString, user.getId());
            var currentMonthSumUp = splittingService.getMonthlySumUp(SplittingService.TYPE_ONLINE, currentMonthString, user.getId());
            userInfoVo.setVipOnline(sumUp.getVipLevel().longValue());

            userInfoVo.setVip5CountOnline(currentMonthSumUp.getVip5Count().longValue());
            userInfoVo.setSelfOnlineAmount(currentMonthSumUp.getSelfAmount());
            userInfoVo.setGroupOnlineAmount(currentMonthSumUp.getAmount());
        } catch (Throwable t) {

        }

        try {
            var sumUp = splittingService.getMonthlySumUp(SplittingService.TYPE_OFFLINE, monthString, user.getId());
            var currentMonthSumUp = splittingService.getMonthlySumUp(SplittingService.TYPE_OFFLINE, currentMonthString, user.getId());

            userInfoVo.setVipOffline(sumUp.getVipLevel().longValue());
            userInfoVo.setVip5CountOffline(currentMonthSumUp.getVip5Count().longValue());
            userInfoVo.setSelfOfflineAmount(currentMonthSumUp.getSelfAmount());
            userInfoVo.setGroupOfflineAmount(currentMonthSumUp.getAmount());
        } catch (Throwable t) {

        }


        if (user.getPurchasedVipLevel() != null && user.getPurchasedVipLevel() > MathUtils.max(userInfoVo.getVipOnline(), userInfoVo.getVipCps(), userInfoVo.getVipOffline())) { // 代理商写死等级覆盖
            userInfoVo.setVipOnline((long) user.getPurchasedVipLevel());
            userInfoVo.setVipCps((long) user.getPurchasedVipLevel());
            userInfoVo.setVipOffline((long) user.getPurchasedVipLevel());
        }
        user.setPurchasedVipLevel(null); // 强改等级不返回到客户端


        if (user.getId().equals(currentUserId)) { // 仅登录态本身可见的用户信息
            userInfoVo.setIncome(splittingService.getUserApproximatelyIncome(user.getId()));
            userInfoVo.setCpsRelationId(cpsService.getCpsUserInfo(user.getId()).getRelationId());

            if (user.getVipType() == User.VipType.PRIME) {
                userInfoVo.setVipRemainTime(DateUtils.daysBetweenToday(user.getPrimeVipValidation()) + "天");
            } else if (user.isTempVip()) {
                userInfoVo.setVipRemainTime(DateUtils.daysBetweenToday(user.getVipValidation()) + "天");
            }

        }

        Calendar c = Calendar.getInstance();
        DateUtils.setFirstTimeOfDay(c);

        userInfoVo.setFollowerTodayIncrease(userService.getInviteeCountRegisterAfter(user.getId(), c.getTime()));

        c.set(Calendar.DAY_OF_MONTH, 1);
        userInfoVo.setFollowerThisMonthIncrease(userService.getInviteeCountRegisterAfter(user.getId(), c.getTime()));

        return userInfoVo;
    }
}
